package common

import (
	"encoding/binary"
	"strconv"

	"github.com/golang/protobuf/proto"
	pbcom "hundsun.com/hsl/hschain/protos/common"
	"hundsun.com/hsl/hschain/protos/manage"
	"hundsun.com/hsl/hschain/store/db"
	"hundsun.com/hsl/hschain/store/extend/ledger"
)

const (
	// NativeManage 合约名
	NativeManage = "nativeManage"
	// QueryManageFlowStatus 查询流程状态
	QueryManageFlowStatus = "Status"
	// QueryCreatedManageFlow 查询创建的流程
	QueryCreatedManageFlow = "Created"
	// QueryVotedManageFlow 查询投票的流程
	QueryVotedManageFlow = "Voted"
	// QueryNeedVotedManageFlow 查询待投票的流程
	QueryNeedVotedManageFlow = "NeedVoted"
	// QueryUserGroup 查询用户分组信息
	QueryUserGroup = "UserGroup"
	// QueryManageFlowCfg 查询流程配置
	QueryManageFlowCfg = "Cfg"
	//QueryCreatedManageFlowByAddr =查询流程
	QueryCreatedManageFlowByAddr = "QueryCreatedManageFlowByAddr"
	//QueryManageFlowSetProposal = 据flowID修改proposal
	QueryManageFlowSetProposal = "QueryManageFlowSetProposal"
	// QueryVoteHistoryByFlowID = 查看指定流程投票历史记录
	QueryVoteHistoryByFlowID = "QueryVoteHistoryByFlowID"
)

const (
	// TyLogCreateManageFlow ...
	TyLogCreateManageFlow = 1000
	// TyLogCreateManageFlowCfg ...
	TyLogCreateManageFlowCfg = 1010
	// TyLogVoteManageFlow ...
	TyLogVoteManageFlow = 1020
	// TyLogVoteHistory ...
	TyLogVoteHistory = 1030
	// TyLogModifyManageFlow ...
	TyLogModifyManageFlow = 1040
	// TyLogCloseManageFlow ...
	TyLogCloseManageFlow = 1050
	// TyLogUpdateManageFlowID ...
	TyLogUpdateManageFlowID = 1060
	// TyLogUserGroupUpdate ...
	TyLogUserGroupUpdate = 1070
	// TyLogSysParamUpdate ...
	TyLogSysParamUpdate = 1080
	// TyLogConsensusUpdate ...
	TyLogConsensusUpdate = 1090
)

// manageFlowTypeMap 流程类型对应字符串
var manageFlowTypeMap = map[manage.ProposalType]string{
	0: "UnknownFlowType",
	1: "CommitteeElection",
	2: "SubCommitteeElection",
}

// manageFlowStateMap 流程状态对应字符串
var manageFlowStateMap = map[manage.ManageFlowState]string{
	0: "UnknownFlowStatus",
	1: "InitFlowStatus",
	2: "RunningFLowStatus",
	3: "SuccessFlowStatus",
	4: "ExpiredFlowStatus",
	5: "FailedFlowStatus",
}

// GetManageFlowTypeStr 获取流程类型字符串
func GetManageFlowTypeStr(flowType manage.ProposalType) string {
	return manageFlowTypeMap[flowType]
}

// GetManageFlowStateStr 获取流程状态字符串
func GetManageFlowStateStr(state manage.ManageFlowState) string {
	return manageFlowStateMap[state]
}

// IDKV kv化
func IDKV(flowID uint32) (*pbcom.KeyValue, error) {
	v := make([]byte, 8)
	binary.BigEndian.PutUint32(v, flowID)
	return &pbcom.KeyValue{Key: GenIDKey(), Value: v}, nil
}

// GenIDKey 生成管理流程ID的key
func GenIDKey() []byte {
	return ledger.GenKey(db.NamespaceManageFlowID, "")
}

// CfgKV 管理流程配置定义KV
func CfgKV(cfg *manage.ManageFlowCfg) (*pbcom.KeyValue, error) {
	kv := &pbcom.KeyValue{}
	v, err := proto.Marshal(cfg)
	if err != nil {
		return nil, err
	}
	kv.Value = v
	kv.Key = GenCfgKey(cfg.Name)
	return kv, nil
}

// GenCfgKey 生成管理流程配置的key
func GenCfgKey(flowName string) []byte {
	return ledger.GenKey(db.NamespaceManageFlowCfg, flowName)
}

// StatusKV 管理流程实例KV化
func StatusKV(status *manage.ManageFlowStatus) (*pbcom.KeyValue, error) {
	return ledger.KV(status.GetXXXNamespace(), status)
}

// GenStatusKey 生成管理流程状态的key
func GenStatusKey(flowID uint32) []byte {
	return ledger.GenKey(db.NamespaceManageFlowStatus, strconv.Itoa(int(flowID)))
}

// PeerIDLength PeerID length
var PeerIDLength = 46

const (
	// GenesisValidatorCfg genesis validator config
	GenesisValidatorCfg = "gen_val_cfg"
	// MainValidatorCfg main validator config
	MainValidatorCfg = "main_val_cfg"
	// DefaultCfgVersion default config version
	DefaultCfgVersion = "1.0.0"

	// VoteExecName ...
	VoteExecName = "vote"
	// VotePreExecName ...
	VotePreExecName = "votepre"
	// CommitExecName ...
	CommitExecName = "commit"
	// ProposalContinuousHeight proposal continuous height ...
	ProposalContinuousHeight = 10000
	// ProposalEffectivePercent proposal effective percent ...
	ProposalEffectivePercent = float32(2 / 3.0)

	// DefaultMaxBlocksInTimeSlice ...
	DefaultMaxBlocksInTimeSlice = 6
	// DefaultTimeSliceLength ...
	DefaultTimeSliceLength = 3
	// DefaultRoundInterval ...
	DefaultRoundInterval = 1
)

// GenDefaultMainValidatorFlowCfg 获取委员会提案流程默认配置项
func GenDefaultMainValidatorFlowCfg(height uint64) *manage.ManageFlowCfg {
	return &manage.ManageFlowCfg{
		Name: MainValidatorCfg,
		Nodes: []*manage.ManageFlowNode{
			{
				ExecName: VotePreExecName,
				Properties: &manage.ExecProperties{
					ExecExternally: true,
					Conditions: []*manage.ExecCondition{
						{
							Type: manage.ConditionType_ExistConditionType,
						},
					},
				},
			},
			{
				ExecName: VoteExecName,
				Properties: &manage.ExecProperties{
					ExecExternally: true,
					Conditions: []*manage.ExecCondition{
						{
							Type:          manage.ConditionType_PercentConditionType,
							ExpectPercent: ProposalEffectivePercent,
						},
					},
				},
			},
			{
				ExecName: CommitExecName,
			},
		},
		StartHeight: height,
		EndHeight:   height + ProposalContinuousHeight,
	}
}
